package com.czxy.enterprise.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.czxy.domain.TbEnterprise;
import com.czxy.domain.TbRecruitmentInfo;
import com.czxy.domain.TbUserLog;
import com.czxy.domain.TbWelfare;
import com.czxy.enterprise.mapper.TbUserLogMapper;
import com.czxy.enterprise.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户及日志 服务实现类
 * </p>
 *
 * @author xuewen
 * @since 2022-03-09
 */
@Service
public class TbUserLogServiceImpl extends ServiceImpl<TbUserLogMapper, TbUserLog> implements TbUserLogService {
    @Resource
    private RecruitmentInfoService recruitmentInfoService;
    @Autowired
    private OccupationService occupationService;
    @Autowired
    private WelfareService welfareService;
    @Autowired
    private CityService cityService;
    @Autowired
    private EnterpriseService enterpriseService;

    public Map<Double, Integer> computeNearestNeighbor(Integer id){
        Map<Double, Integer> distances = new TreeMap<>();
        List<TbUserLog> list = this.baseMapper.selectList(null);
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id",id);
        List<TbUserLog> u1 = this.baseMapper.selectList(queryWrapper);
        List<Integer> collect = list.stream().map(tbUserLog -> tbUserLog.getUserId()).collect(Collectors.toList());
        for (Integer integer : collect) {
            if (integer!=id){
                QueryWrapper queryWrapper1 = new QueryWrapper();
                queryWrapper1.eq("user_id",integer);
                List<TbUserLog> u2 = this.baseMapper.selectList(queryWrapper1);
                double distance = pearson_dis(u2, u1);
                distances.put(distance, integer);
            }

        }
        System.out.println(distances);
        return distances;
    }
    /**
     * 计算2个打分序列间的pearson距离
     *
     * @param rating1
     * @param rating2
     * @return
     */
    private double pearson_dis(List<TbUserLog> rating1, List<TbUserLog> rating2) {
        int sum_xy = 0;
        int sum_x = 0;
        int sum_y = 0;
        double sum_x2 = 0;
        double sum_y2 = 0;
        int n = 0;
        for (int i = 0; i < rating1.size(); i++) {
            TbUserLog key1 = rating1.get(i);
            for (int j = 0; j < rating2.size(); j++) {
                TbUserLog key2 = rating2.get(j);
                if (key1.getInfoId()==(key2.getInfoId())) {
                    n += 1;
                    int x = key1.getScore();
                    int y = key2.getScore();
                    sum_xy += x * y;
                    sum_x += x;
                    sum_y += y;
                    sum_x2 += Math.pow(x, 2);
                    sum_y2 += Math.pow(y, 2);
                }

            }
        }
        double denominator = Math.sqrt(sum_x2 - Math.pow(sum_x, 2) / n) * Math.sqrt(sum_y2 - Math.pow(sum_y, 2) / n);
        if (denominator == 0) {
            return 0;
        } else {
            return (sum_xy - (sum_x * sum_y) / n) / denominator;
        }
    }

    @Override
    public List<TbRecruitmentInfo> recommend(Integer userId) {
        List<TbUserLog> recommendations = new ArrayList<>();
        //找到最近邻
        Map<Double, Integer> distances = computeNearestNeighbor(userId);
        List<Integer> distancesList = new ArrayList<>();
        for (Double aDouble : distances.keySet()) {
            if (aDouble>=0.0){
                distancesList.add(distances.get(aDouble));
            }
        }
        for (Integer nearest : distancesList) {
            //找到最近邻看过，但是我们没看过的电影，计算推荐
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("user_id",nearest);
            List<TbUserLog> list1 = this.baseMapper.selectList(queryWrapper);

            QueryWrapper queryWrapper1 = new QueryWrapper();
            queryWrapper1.eq("user_id",userId);
            List<TbUserLog> list2 =this.baseMapper.selectList(queryWrapper1);

//        for (UserSet.Set artist : neighborRatings.list) {
////            if (userRatings.find(artist.username) == null) {
////                recommendations.add(artist);
////            }
//        }
            List<Integer> collect = list2.stream().map(tbUserLog -> tbUserLog.getInfoId()).collect(Collectors.toList());
            for (TbUserLog tbUserLog : list1) {
                if (!collect.contains(tbUserLog.getInfoId())){
//                    System.out.println(tbUserLog);
                    recommendations.add(tbUserLog);
                }
            }
        }
//        Collections.sort(recommendations);
        System.out.println("recommendations -> " + recommendations.toString());
        Collections.sort(recommendations, new Comparator<TbUserLog>() {
            @Override
            public int compare(TbUserLog o1, TbUserLog o2) {
                return o1.getScore()-o2.getScore();
            }
        });
        List<Integer> ids = recommendations.stream().map(tbUserLog ->{
            if (tbUserLog.getScore()>2){
                return  tbUserLog.getInfoId();
            }else {
                return null;
            }
        }).collect(Collectors.toList());
//        return recommendations;
        List<TbRecruitmentInfo> list = null;
        if(ids.size()>0) {
            list = recruitmentInfoService.listByIds(ids);

            for (TbRecruitmentInfo record : list) {
                //地址
                record.setTbCity(cityService.getById(record.getAddressId()));
                //种类
                record.setTbOccupation(occupationService.getById(record.getOccupationId()));
                //福利
                String welfareIds = record.getWelfareIds();
                String[] split = welfareIds.split(",");
                List<String> welfareIdList = Arrays.asList(split);
                List<TbWelfare> welfareList = new ArrayList<>();
                for (String s : welfareIdList) {
                    if (StringUtils.isNotBlank(s)) {
                        welfareList.add(welfareService.getById(s));
                    }
                }
                record.setWelfares(welfareList);
                //赋值企业的数据
                TbEnterprise tbEnterprise = enterpriseService.findById(record.getEnterpriseId());
                record.setTbEnterprise(tbEnterprise);

            }
        }
        return list;
    }
}
